/**
 * WebSocket连接测试工具
 * 用于检测WebSocket服务器连接情况
 */

/**
 * 测试WebSocket连接
 * @param {string} url - WebSocket URL
 * @param {Object} options - 配置选项
 * @param {number} options.timeout - 连接超时时间(毫秒)
 * @param {Function} options.onOpen - 连接成功回调
 * @param {Function} options.onMessage - 收到消息回调
 * @param {Function} options.onError - 错误回调
 * @param {Function} options.onClose - 关闭回调
 * @param {Function} options.onTimeout - 超时回调
 * @param {Object} options.headers - 自定义头信息 (用于WebSocket握手)
 * @param {Object} options.heartbeat - 心跳设置 {enabled, message, interval}
 * @returns {Promise}
 */
export function testWebSocketConnection(url, options = {}) {
  const {
    timeout = 5000,
    onOpen = () => {},
    onMessage = () => {},
    onError = () => {},
    onClose = () => {},
    onTimeout = () => {},
    headers = {},
    heartbeat = { enabled: false, message: 'PING', interval: 30000 }
  } = options;

  console.log(`开始测试WebSocket连接: ${url}`);
  
  // 返回一个Promise以便异步处理结果
  return new Promise((resolve, reject) => {
    try {
      // 设置超时
      const timeoutId = setTimeout(() => {
        console.error(`WebSocket连接超时: ${url}`);
        onTimeout();
        reject(new Error('WebSocket connection timeout'));
        // 如果socket仍在连接中，关闭它
        if (socket && socket.readyState === WebSocket.CONNECTING) {
          socket.close();
        }
      }, timeout);
      
      // 创建WebSocket连接，支持协议和扩展
      let socket;
      if (typeof headers === 'object' && Object.keys(headers).length > 0) {
        // 在支持的浏览器中尝试使用headers
        try {
          socket = new WebSocket(url);
          console.log('使用标准WebSocket连接 (不支持自定义headers)');
        } catch (e) {
          console.error('创建带自定义headers的WebSocket失败:', e);
          socket = new WebSocket(url);
        }
      } else {
        socket = new WebSocket(url);
      }
      
      let heartbeatTimer = null;
      
      // 连接建立时
      socket.onopen = (event) => {
        console.log(`WebSocket连接成功: ${url}`);
        clearTimeout(timeoutId);
        onOpen(event);
        
        // 设置心跳
        if (heartbeat.enabled) {
          console.log(`启用心跳检测，间隔: ${heartbeat.interval}ms`);
          heartbeatTimer = setInterval(() => {
            if (socket.readyState === WebSocket.OPEN) {
              console.log(`发送心跳: ${heartbeat.message}`);
              socket.send(heartbeat.message);
            }
          }, heartbeat.interval);
        }
        
        resolve({
          success: true,
          socket,
          message: 'Connection established successfully',
          stopHeartbeat: () => {
            if (heartbeatTimer) {
              clearInterval(heartbeatTimer);
              heartbeatTimer = null;
            }
          }
        });
      };
      
      // 收到消息时
      socket.onmessage = (event) => {
        console.log(`WebSocket收到消息: ${event.data}`);
        onMessage(event);
      };
      
      // 发生错误时
      socket.onerror = (event) => {
        console.error(`WebSocket连接错误: ${url}`, event);
        clearTimeout(timeoutId);
        if (heartbeatTimer) {
          clearInterval(heartbeatTimer);
        }
        onError(event);
        reject({
          success: false,
          error: event,
          message: 'Connection error',
          readyState: socket.readyState,
          // 添加更多诊断信息
          diagnosis: {
            url,
            readyState: getReadyStateDescription(socket.readyState),
            browser: getBrowserInfo(),
            time: new Date().toISOString()
          }
        });
      };
      
      // 连接关闭时
      socket.onclose = (event) => {
        console.log(`WebSocket连接关闭: ${url}, 状态码: ${event.code}, 原因: ${event.reason}`);
        clearTimeout(timeoutId);
        if (heartbeatTimer) {
          clearInterval(heartbeatTimer);
        }
        onClose(event);
        
        // 如果不是正常关闭，视为连接失败
        if (event.code !== 1000) {
          reject({
            success: false,
            error: event,
            message: `Connection closed with code ${event.code}`,
            diagnosis: {
              url,
              code: event.code,
              reason: event.reason || 'Unknown reason',
              wasClean: event.wasClean,
              readyState: getReadyStateDescription(socket.readyState),
              browser: getBrowserInfo(),
              time: new Date().toISOString()
            }
          });
        }
      };
      
      // 返回socket以便调用者可以手动关闭
      return socket;
    } catch (error) {
      console.error(`创建WebSocket连接失败: ${url}`, error);
      reject({
        success: false,
        error,
        message: error.message,
        diagnosis: {
          url,
          browser: getBrowserInfo(),
          time: new Date().toISOString(),
          errorType: error.name,
          errorMessage: error.message
        }
      });
    }
  });
}

/**
 * 测试多个WebSocket端点
 * @param {Array<string|Object>} endpoints - WebSocket URL数组或配置对象数组 [{url, options}]
 * @param {Object} defaultOptions - 默认选项
 * @returns {Promise<Array>} 测试结果数组
 */
export function testMultipleEndpoints(endpoints, defaultOptions = {}) {
  console.log(`开始测试多个WebSocket端点: ${endpoints.length} 个`);
  
  const results = [];
  
  // 规范化输入
  const normalizedEndpoints = endpoints.map(ep => {
    if (typeof ep === 'string') {
      return { url: ep, options: defaultOptions };
    }
    return { 
      url: ep.url, 
      options: { ...defaultOptions, ...ep.options } 
    };
  });
  
  // 依次测试每个URL
  return normalizedEndpoints.reduce((promise, endpoint) => {
    return promise.then(() => {
      console.log(`测试端点: ${endpoint.url}`);
      return testWebSocketConnection(endpoint.url, endpoint.options)
      .then(result => {
        const testResult = { 
          url: endpoint.url, 
          status: 'success', 
          result,
          timestamp: new Date().toISOString()
        };
        results.push(testResult);
        // 连接成功后立即关闭
        if (result.socket && result.socket.readyState === WebSocket.OPEN) {
          // 如果有心跳，先停止
          if (typeof result.stopHeartbeat === 'function') {
            result.stopHeartbeat();
          }
          result.socket.close();
        }
        return results;
      })
      .catch(error => {
        const testResult = { 
          url: endpoint.url, 
          status: 'failure', 
          error,
          timestamp: new Date().toISOString()
        };
        results.push(testResult);
        return results;
      });
    });
  }, Promise.resolve());
}

/**
 * 测试多个端口的WebSocket连接
 * @param {string} host - 主机名
 * @param {string} path - WebSocket路径
 * @param {Array<number>} ports - 要测试的端口数组
 * @param {string} protocol - 协议 (ws 或 wss)
 * @param {Object} options - 连接选项
 * @returns {Promise<Array>} 测试结果数组
 */
export function testMultiplePorts(host, path, ports, protocol = 'ws', options = {}) {
  const endpoints = ports.map(port => `${protocol}://${host}:${port}${path}`);
  return testMultipleEndpoints(endpoints, options);
}

/**
 * 测试WebSocket连接并模拟心跳交互
 * @param {string} url - WebSocket URL
 * @param {Object} options - 配置选项
 * @returns {Promise}
 */
export function testWithHeartbeat(url, options = {}) {
  const heartbeatOptions = {
    enabled: true,
    message: 'PING',
    interval: 10000,
    expectedResponse: 'pong',
    timeout: 5000,
    ...options.heartbeat
  };
  
  return new Promise((resolve, reject) => {
    console.log(`开始带心跳测试WebSocket连接: ${url}`);
    
    let heartbeatTimer = null;
    let heartbeatTimeoutTimer = null;
    let heartbeatResponseReceived = false;
    let heartbeatCount = 0;
    const maxHeartbeats = options.maxHeartbeats || 3;
    
    const testOptions = {
      ...options,
      onOpen: (event) => {
        console.log('WebSocket连接已打开，等待发送心跳...');
        if (options.onOpen) options.onOpen(event);
        
        // 延迟发送第一个心跳
        setTimeout(() => {
          if (socket && socket.readyState === WebSocket.OPEN) {
            sendHeartbeat();
          }
        }, 1000);
      },
      onMessage: (event) => {
        console.log(`收到消息: ${event.data}`);
        if (options.onMessage) options.onMessage(event);
        
        // 检查是否为心跳响应
        if (event.data === heartbeatOptions.expectedResponse) {
          console.log('收到心跳响应!');
          heartbeatResponseReceived = true;
          clearTimeout(heartbeatTimeoutTimer);
          
          heartbeatCount++;
          if (heartbeatCount >= maxHeartbeats) {
            console.log(`完成 ${maxHeartbeats} 次心跳交换，测试成功!`);
            cleanup();
            resolve({
              success: true,
              message: `完成 ${maxHeartbeats} 次心跳交换`,
              heartbeats: heartbeatCount
            });
          }
        }
      },
      onClose: (event) => {
        console.log(`WebSocket连接关闭: ${event.code}`);
        cleanup();
        if (options.onClose) options.onClose(event);
      },
      onError: (event) => {
        console.error('WebSocket错误');
        cleanup();
        if (options.onError) options.onError(event);
        reject({
          success: false,
          message: 'WebSocket连接错误',
          error: event
        });
      }
    };
    
    // 发送心跳
    const sendHeartbeat = () => {
      if (socket && socket.readyState === WebSocket.OPEN) {
        console.log(`发送心跳: ${heartbeatOptions.message}`);
        socket.send(heartbeatOptions.message);
        heartbeatResponseReceived = false;
        
        // 设置心跳响应超时
        heartbeatTimeoutTimer = setTimeout(() => {
          if (!heartbeatResponseReceived) {
            console.error('心跳响应超时!');
            cleanup();
            reject({
              success: false,
              message: '心跳响应超时',
              heartbeats: heartbeatCount
            });
          }
        }, heartbeatOptions.timeout);
        
        // 设置下一次心跳
        heartbeatTimer = setTimeout(sendHeartbeat, heartbeatOptions.interval);
      }
    };
    
    // 清理资源
    const cleanup = () => {
      if (heartbeatTimer) {
        clearTimeout(heartbeatTimer);
        heartbeatTimer = null;
      }
      if (heartbeatTimeoutTimer) {
        clearTimeout(heartbeatTimeoutTimer);
        heartbeatTimeoutTimer = null;
      }
      if (socket && socket.readyState === WebSocket.OPEN) {
        socket.close();
      }
    };
    
    const socket = testWebSocketConnection(url, testOptions);
  });
}

/**
 * 获取WebSocket readyState的描述
 */
function getReadyStateDescription(readyState) {
  switch(readyState) {
    case WebSocket.CONNECTING: 
      return { code: 0, description: 'CONNECTING - The connection is not yet open.' };
    case WebSocket.OPEN: 
      return { code: 1, description: 'OPEN - The connection is open and ready to communicate.' };
    case WebSocket.CLOSING: 
      return { code: 2, description: 'CLOSING - The connection is in the process of closing.' };
    case WebSocket.CLOSED: 
      return { code: 3, description: 'CLOSED - The connection is closed or couldn\'t be opened.' };
    default: 
      return { code: readyState, description: 'UNKNOWN' };
  }
}

/**
 * 获取浏览器信息
 */
function getBrowserInfo() {
  const ua = navigator.userAgent;
  return {
    userAgent: ua,
    browser: getBrowserName(ua),
    platform: navigator.platform,
    vendor: navigator.vendor,
  };
}

/**
 * 获取浏览器名称
 */
function getBrowserName(ua) {
  if (ua.indexOf("Edge") > -1) return "Edge";
  if (ua.indexOf("Chrome") > -1) return "Chrome";
  if (ua.indexOf("Firefox") > -1) return "Firefox";
  if (ua.indexOf("Safari") > -1) return "Safari";
  if (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident/") > -1) return "Internet Explorer";
  return "Unknown";
}

/**
 * 解析WebSocket关闭代码
 * @param {number} code - 关闭代码
 * @returns {string} 关闭代码的描述
 */
export function getWebSocketCloseDescription(code) {
  const codeMap = {
    1000: "正常关闭",
    1001: "终端离开",
    1002: "协议错误",
    1003: "不支持的数据",
    1004: "保留",
    1005: "没有收到预期的状态码",
    1006: "异常关闭",
    1007: "无效的帧数据",
    1008: "违反策略",
    1009: "消息太大",
    1010: "需要扩展",
    1011: "内部错误",
    1012: "服务重启",
    1013: "稍后重试",
    1014: "网关问题",
    1015: "TLS握手失败"
  };
  
  return codeMap[code] || `未知关闭代码: ${code}`;
} 